from rest_framework.viewsets import ViewSet
from rest_framework.permissions import IsAuthenticated
from course.models import Course
from rest_framework.response import Response
from rest_framework import status
from django_redis import get_redis_connection
import logging
from skylark_api.settings import constants

log = logging.getLogger("django")


# 必须要对应的用户才能看到，用户必须登陆之后才能查看
class CartAPIView(ViewSet):
    """购物车"""
    # 确保只有登陆用户才能访问购物车功能
    permission_classes = [IsAuthenticated]

    def add(self, request):
        """添加商品到购物车"""
        # 确认课程，才能添加到购物车，redis数据,获取course_id
        course_id = request.data.get('course_id')
        print(course_id)
        # 获取用户id
        user_id = request.user.id
        # 检查商品是否存在于购物车中
        try:
            # 获取单个课程信息
            course = Course.objects.get(is_show=True, is_deleted=False, id=course_id)

        except Course.DoesNotExist:
            return Response({"message": "参数有误，课程不存在!"}, status=status.HTTP_400_BAD_REQUEST)

        # 将商品添加到数据库中
        redis_conn = get_redis_connection("cart")

        try:
            # 提示已存在

            if redis_conn.hexists(f"cart_{user_id}", course_id):
                return Response({'message': '课程已存在于购物车中！', "cart_length": redis_conn.hlen(f"cart_{user_id}")})

            # 保存课程到购物车
            # 管道允许多个redis命令打包在一起，一次性发送到redis服务器执行
            pipe = redis_conn.pipeline()
            # 开启一个redis事务
            # 确保事务所有命令按照顺序执行，不会被其他客户端打断的命令打断
            pipe.multi()
            # 存储到数据库里面
            #           使用hash存储商品id和有效期
            #       使用set 存储被选中的商品id
            pipe.hset(f"cart_{user_id}", course_id, 0)  # 默认有效期
            pipe.sadd(f"selected_{user_id}", course_id)  # 默认勾选
            # 提交到redis数据库中
            pipe.execute()

            # 统计课程选中的总数
            course_len = redis_conn.hlen(f"cart_{user_id}")
            log.info(f"用户{user_id}添加课程{course_id}到购物车, 当前购物车商品总数: {course_len}")

        except Exception as e:
            log.error(f"购物车数据存储错误: {str(e)}")
            return Response({'message': '服务器错误，购物车添加课程失败！'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)

        # 返回添加成功信息
        return Response({'message': "购物车课程添加成功！", "cart_length": course_len})

    # 获取商品
    def list(self, request):
        """获取购物车商品列表"""
        # 获取用户ID
        user_id = request.user.id
        # 获取redis链接对象cart
        redis_conn = get_redis_connection("cart")
        # 获取用户购物车
        cart_course_list = redis_conn.hgetall(f"cart_{user_id}")
        # 获取用户的选项
        cart_selected_list = redis_conn.smembers(f"selected_{user_id}")

        if len(cart_course_list) < 1:
            return Response({"cart_length": 0, "data": []})  # 返回空列表和购物车数量

        data = []
        # course_bytes，expire_bytes 是从redis获取的数据，redis返回的数据是字节类型(bytes)
        # 需要解码才能转换为字符串

        for course_bytes, expire_bytes in cart_course_list.items():

            course_id = course_bytes.decode()

            try:
                course = Course.objects.get(pk=course_id)

            except Course.DoesNotExist:
                continue

            data.append({
                "id": course_id,
                "name": course.name,
                "course_img": f"{constants.SERVER_IMAGE_DOMAIN}{course.course_img.url}",
                "price": course.price,
                # 判断当前商品是否被选中
                # cart_selected_list是一个哈希字典
                # 课程id是否存在于cart_selected_list中
                "is_selected": True if course_bytes in cart_selected_list else False
            })

        cart_length = len(data)  # 计算购物车商品总数
        return Response({"cart_length": cart_length, "data": data})  # 返回购物车数量和商品列表


    def change_selected(self, request):
        """修改选中状态"""
        """
        1.获取selected
        2.获取到用户
        3.查询redis数据
        4.修改勾选状态
        5.返回结果
        
        """
        user_id = request.user.id
        selected = request.data.get('selected')

        # true false
        course_id = request.data.get('course_id')
        try:
            Course.objects.get(is_deleted=False, is_show=True, id=course_id)
        except Course.DoesNotExist:
            return Response({'message': '参数有误！当前课程数据不存在！'}, status=status.HTTP_400_BAD_REQUEST)

        redis_conn = get_redis_connection("cart")
        if selected:
            redis_conn.sadd("selected_%s" % user_id, course_id)
        else:
            redis_conn.srem("selected_%s" % user_id, course_id)

        return Response({'message': '切换勾选状态成功！'})
